/********************************************************************************************************************************
 * 《C ++ Primer》第五版中文版，读书笔记：按照书中的的示例源码和每一个小章节的课后习题，自己动手写代码实现，作为联系和测试。
 * Date: 2024-03-26 10:16
 * Author: dimon.chen 
 * EMali: 1181302388@qq.com 
 * 
 * 章节: 第二章 变量和基本类型
 *       2.4.3 顶层const (top-level const)
 *             底层const (low-level const)
 * 
 ********************************************************************************************************************************/

/// 更一般的顶层const是表示任意的对象是常量，这对任何的类型都适用，包括算数类型，类，指针等
/// 底层const和符合类型如引用和指针的基本数据类型有关

#include <iostream>

int main(int argc, char *argv[])
{
	
	///
	/// 2.4.3 顶层const
	/// 练习2.30：对于下面的这些语句，请说明那些对象被声明成了顶层const还是底层const？
	///
	
	int i = 0;
	//v2的值不能改变，v2是一个顶层const
	const int v2 = 0;
	//v1是普通的整型（非常量），v2是顶层const，在拷贝时顶层const没有影响
	int v1 = v2;
	//p1是指向整型的指针, &v1是普通指针, &v1赋值给p1允许
	//r1是引用，指向一个普通整型，r1绑定到普通int型v1允许
	int *p1 = &v1, &r1 = v1;
	//p2指向int型常量，p2是一个底层const，&v2是一个底层const ， &v2赋值给p2合法
	//p3既是一个顶层const又是一个底层const，int *可以转换成 const int *，p3初始化为 &i允许
	//r2是一个常量引用（指向常量的引用），一个常量引用初始化时可以绑定到非常量引用，字面值，甚至一个计算表达式。
	const int *p2 = &v2, *const p3 = &i, &r2 = v2;
	
	///
	/// 2.4.3 顶层const
	/// 练习2.31：假设已有上一个练习中所作的那些声明，则下面的那些语句是合法的？
	/// 		 请说明顶层const和底层const在每个例子中是如何体现的。

	// 正确:
	//r1是一个引用指向int型对象，对引用赋值，结果是对引用绑定的对象赋值
	//v1是int型对象，v1 = v1 赋值合法
	r1 = v1;

	//错误
	//p1 是一个指针指向int性对象, p1 类型是 int *, p2 是一个指向常量的指针，p2是一个底层const
	//p1 = p2，底层const类型，const int * 不能转换成非常量指针类型
	p1 = p2;
	//p2 = p1 正确, p2是底层const，p1是 int * 类型，int *可以转换成 const int *
	p2 = p1;

	//错误
	//p3既是顶层const又是底层const，在赋值拷贝时顶层const对操没有影响，但是p3是底层const，把
	//底层const赋值给p1指向非常量的指针错误
	p1 = p3; 

	//正确
	//p3既是顶层const又是底层const，在赋值拷贝时顶层const对操没有影响，
	//p2是底层const，p3也是底层const , p3赋值给p2允许
	p2 = p3;
}